/** 
 * Project Name: farm-core 
 * File Name: DefaultValidateHandler.java 
 * Package Name: com.bugull.farm.core.handler 
 * Date: 2017年3月22日下午5:08:58 
 * Copyright (c) 2017, hadlinks All Rights Reserved. 
 * 
 */
package com.bugull.farm.core.handler;

import java.util.List;

import org.apache.logging.log4j.*;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import com.bugull.farm.core.cache.PropertiesCache;
import com.bugull.farm.core.cache.ProtocolCache;
import com.bugull.farm.core.frame.structure.Param;
import com.bugull.farm.core.utils.ByteUtil;

/** 
 * ClassName: DefaultValidateHandler 
 * Function: TODO ADD FUNCTION.  
 * date: 2017年3月22日 下午5:08:58  
 * 
 * @author songwei (songw@hadlinks.com)
 * @version 
 * @since JDK 1.8 
 */
public class DefaultValidateHandler extends SimpleChannelInboundHandler<ByteBuf>{
	
	private final Logger logger = LogManager.getLogger(DefaultValidateHandler.class);
	private PropertiesCache props = PropertiesCache.getInstance();

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg)
			throws Exception {
		
		//协议格式校验
		//校验协议长度
		if(msg.readableBytes() < props.getInt("frame.min.size")){
			ctx.close();
			logger.error("Too short to recognize the message!!!"+ByteBufUtil.hexDump(msg));
		}
		//校验协议头
		if(!ByteBufUtil.hexDump(msg, ProtocolCache.getInstance().getIndex("pv"), 1).equals(props.get("pv"))){
			ctx.writeAndFlush(getErrorResponse(props.getByte("error.protocol"), msg)).addListener(ChannelFutureListener.CLOSE);
			logger.error("Non conformity protocol , pv is not correct!!!");
		}
		//校验厂家代码
		if(!ByteBufUtil.hexDump(msg, ProtocolCache.getInstance().getIndex("companyCode"), 1).equals(props.get("companyCode"))){
			ctx.writeAndFlush(getErrorResponse(props.getByte("error.protocol"), msg)).addListener(ChannelFutureListener.CLOSE);
			logger.error("Non conformity protocol , companyCode is not correct!!!");
		}
		//校验设备类型
		if(!ByteBufUtil.hexDump(msg, ProtocolCache.getInstance().getIndex("deviceType"), 1).equals(props.get("deviceType"))){
			ctx.writeAndFlush(getErrorResponse(props.getByte("error.protocol"), msg)).addListener(ChannelFutureListener.CLOSE);
			logger.error("Non conformity protocol , deviceType is not correct!!!");
		}
	}

	/**
	 * 拼装服务器反馈的错误信息
	 * @param errorCode
	 * @param msg
	 * @return
	 */
	public ByteBuf getErrorResponse(byte errorCode, ByteBuf msg){
		ByteBuf buf = Unpooled.buffer();
		//设置PV
		buf.writeZero(PropertiesCache.getInstance().getInt("frame.min.size"));
		List<Param> headList = ProtocolCache.getInstance().getHead();
		headList.forEach((param) -> {
			if(PropertiesCache.getInstance().getProps().containsKey(param.getName())){
				buf.setBytes(ProtocolCache.getInstance().getIndex(param.getName()), PropertiesCache.getInstance().getBytes(param.getName()));
			}else{
				buf.setBytes(ProtocolCache.getInstance().getIndex(param.getName()), msg.copy(ProtocolCache.getInstance().getIndex(param.getName()), param.getLen()));
			}
		});
		//设置cmd
		buf.setByte(ProtocolCache.getInstance().getIndex("cmd"), PropertiesCache.getInstance().getByte("cmd.error"));
		//设置errorCmd
		buf.writeByte(msg.getByte(ProtocolCache.getInstance().getIndex("cmd")));
		//设置errorCode
		buf.writeByte(errorCode);
		//重新计算长度
		int len = buf.readableBytes() - 1 - ProtocolCache.getInstance().getIndex("len");
		buf.setByte(ProtocolCache.getInstance().getIndex("len"), ByteUtil.fromInt(len)[2]);
		buf.setByte(ProtocolCache.getInstance().getIndex("len"), ByteUtil.fromInt(len)[3]);
		//重新设置协议序号
		buf.setBytes(ProtocolCache.getInstance().getIndex("serial"), PropertiesCache.getInstance().getBytes("serial"));
		return buf;
	}
}
